package network

import (
	"fmt"

	log "github.com/sirupsen/logrus"
	"libvirt.org/go/libvirt"
)

// Service 网络管理服务
type Service struct {
	connManager ConnManager
}

// ConnManager 连接管理器接口
type ConnManager interface {
	WithConn(fn func(*libvirt.Connect) error) error
}

// NewService 创建网络服务
func NewService(cm ConnManager) *Service {
	return &Service{connManager: cm}
}

// NetworkInfo 网络信息
type NetworkInfo struct {
	UUID        string `json:"uuid"`
	Name        string `json:"name"`
	Active      bool   `json:"active"`
	Persistent  bool   `json:"persistent"`
	Autostart   bool   `json:"autostart"`
	Bridge      string `json:"bridge,omitempty"`
	ForwardMode string `json:"forward_mode,omitempty"`
	XMLConfig   string `json:"xml_config,omitempty"`
}

// CreateSpec 创建网络规格
type CreateSpec struct {
	Name        string `json:"name" binding:"required"`
	ForwardMode string `json:"forward_mode"` // nat, route, bridge, none
	Bridge      string `json:"bridge,omitempty"`
	IPAddress   string `json:"ip_address,omitempty"` // 例如: 192.168.100.1
	NetMask     string `json:"netmask,omitempty"`    // 例如: 255.255.255.0
	DHCPStart   string `json:"dhcp_start,omitempty"` // DHCP 起始地址
	DHCPEnd     string `json:"dhcp_end,omitempty"`   // DHCP 结束地址
}

// List 列出所有网络
func (s *Service) List(includeInactive bool) ([]NetworkInfo, error) {
	var networks []NetworkInfo

	err := s.connManager.WithConn(func(conn *libvirt.Connect) error {
		flags := libvirt.CONNECT_LIST_NETWORKS_ACTIVE
		if includeInactive {
			flags |= libvirt.CONNECT_LIST_NETWORKS_INACTIVE
		}

		nets, err := conn.ListAllNetworks(flags)
		if err != nil {
			return fmt.Errorf("failed to list networks: %w", err)
		}

		for _, net := range nets {
			info, err := s.getNetworkInfo(&net, false)
			if err != nil {
				log.Warnf("Failed to get network info: %v", err)
				continue
			}
			networks = append(networks, *info)
			net.Free()
		}
		return nil
	})

	return networks, err
}

// Get 获取网络详情
func (s *Service) Get(name string, includeXML bool) (*NetworkInfo, error) {
	var netInfo *NetworkInfo

	err := s.connManager.WithConn(func(conn *libvirt.Connect) error {
		net, err := conn.LookupNetworkByName(name)
		if err != nil {
			return fmt.Errorf("network not found: %w", err)
		}
		defer net.Free()

		netInfo, err = s.getNetworkInfo(net, includeXML)
		return err
	})

	return netInfo, err
}

// Create 创建网络
func (s *Service) Create(spec *CreateSpec) (*NetworkInfo, error) {
	netXML := s.buildNetworkXML(spec)

	var netInfo *NetworkInfo
	err := s.connManager.WithConn(func(conn *libvirt.Connect) error {
		net, err := conn.NetworkDefineXML(netXML)
		if err != nil {
			return fmt.Errorf("failed to define network: %w", err)
		}
		defer net.Free()

		netInfo, err = s.getNetworkInfo(net, false)
		log.Infof("Network %s created", spec.Name)
		return err
	})

	return netInfo, err
}

// CreateFromXML 从 XML 创建网络
func (s *Service) CreateFromXML(xmlConfig string) (*NetworkInfo, error) {
	var netInfo *NetworkInfo

	err := s.connManager.WithConn(func(conn *libvirt.Connect) error {
		net, err := conn.NetworkDefineXML(xmlConfig)
		if err != nil {
			return fmt.Errorf("failed to define network: %w", err)
		}
		defer net.Free()

		netInfo, err = s.getNetworkInfo(net, false)
		return err
	})

	return netInfo, err
}

// Start 启动网络
func (s *Service) Start(name string) error {
	return s.connManager.WithConn(func(conn *libvirt.Connect) error {
		net, err := conn.LookupNetworkByName(name)
		if err != nil {
			return fmt.Errorf("network not found: %w", err)
		}
		defer net.Free()

		if err := net.Create(); err != nil {
			return fmt.Errorf("failed to start network: %w", err)
		}

		log.Infof("Network %s started", name)
		return nil
	})
}

// Stop 停止网络
func (s *Service) Stop(name string) error {
	return s.connManager.WithConn(func(conn *libvirt.Connect) error {
		net, err := conn.LookupNetworkByName(name)
		if err != nil {
			return fmt.Errorf("network not found: %w", err)
		}
		defer net.Free()

		if err := net.Destroy(); err != nil {
			return fmt.Errorf("failed to stop network: %w", err)
		}

		log.Infof("Network %s stopped", name)
		return nil
	})
}

// Delete 删除网络
func (s *Service) Delete(name string) error {
	return s.connManager.WithConn(func(conn *libvirt.Connect) error {
		net, err := conn.LookupNetworkByName(name)
		if err != nil {
			return fmt.Errorf("network not found: %w", err)
		}
		defer net.Free()

		// 如果网络正在运行，先停止
		active, _ := net.IsActive()
		if active {
			if err := net.Destroy(); err != nil {
				log.Warnf("Failed to stop network before delete: %v", err)
			}
		}

		if err := net.Undefine(); err != nil {
			return fmt.Errorf("failed to undefine network: %w", err)
		}

		log.Infof("Network %s deleted", name)
		return nil
	})
}

// SetAutostart 设置网络自动启动
func (s *Service) SetAutostart(name string, autostart bool) error {
	return s.connManager.WithConn(func(conn *libvirt.Connect) error {
		net, err := conn.LookupNetworkByName(name)
		if err != nil {
			return fmt.Errorf("network not found: %w", err)
		}
		defer net.Free()

		if err := net.SetAutostart(autostart); err != nil {
			return fmt.Errorf("failed to set autostart: %w", err)
		}

		log.Infof("Network %s autostart set to %v", name, autostart)
		return nil
	})
}

// getNetworkInfo 从 libvirt.Network 提取信息
func (s *Service) getNetworkInfo(net *libvirt.Network, includeXML bool) (*NetworkInfo, error) {
	name, err := net.GetName()
	if err != nil {
		return nil, err
	}

	uuid, err := net.GetUUIDString()
	if err != nil {
		return nil, err
	}

	active, err := net.IsActive()
	if err != nil {
		active = false
	}

	persistent, err := net.IsPersistent()
	if err != nil {
		persistent = false
	}

	autostart, err := net.GetAutostart()
	if err != nil {
		autostart = false
	}

	bridge, err := net.GetBridgeName()
	if err != nil {
		bridge = ""
	}

	netInfo := &NetworkInfo{
		UUID:       uuid,
		Name:       name,
		Active:     active,
		Persistent: persistent,
		Autostart:  autostart,
		Bridge:     bridge,
	}

	if includeXML {
		xmlDesc, err := net.GetXMLDesc(0)
		if err != nil {
			log.Warnf("Failed to get XML for network %s: %v", name, err)
		} else {
			netInfo.XMLConfig = xmlDesc
		}
	}

	return netInfo, nil
}

// buildNetworkXML 构建网络 XML
func (s *Service) buildNetworkXML(spec *CreateSpec) string {
	forwardMode := spec.ForwardMode
	if forwardMode == "" {
		forwardMode = "nat"
	}

	xml := fmt.Sprintf(`<network>
  <name>%s</name>`, spec.Name)

	if forwardMode != "none" {
		xml += fmt.Sprintf(`
  <forward mode='%s'/>`, forwardMode)
	}

	if spec.Bridge != "" {
		xml += fmt.Sprintf(`
  <bridge name='%s'/>`, spec.Bridge)
	} else {
		xml += `
  <bridge name='virbr0' stp='on' delay='0'/>`
	}

	// 添加 IP 配置
	if spec.IPAddress != "" && spec.NetMask != "" {
		xml += fmt.Sprintf(`
  <ip address='%s' netmask='%s'>`, spec.IPAddress, spec.NetMask)

		// 添加 DHCP
		if spec.DHCPStart != "" && spec.DHCPEnd != "" {
			xml += fmt.Sprintf(`
    <dhcp>
      <range start='%s' end='%s'/>
    </dhcp>`, spec.DHCPStart, spec.DHCPEnd)
		}

		xml += `
  </ip>`
	}

	xml += `
</network>`
	return xml
}
